package com.xique.door.biz.service.impl;

import com.xique.common.core.text.Convert;
import com.xique.common.core.web.domain.AjaxResult;
import com.xique.door.bean.domain.AccessDevice;
import com.xique.door.bean.domain.PermissionGroupDevice;
import com.xique.door.bean.domain.PermissionGroupUser;
import com.xique.door.bean.domain.UserDevice;
import com.xique.door.bean.request.AccessDevice.AccessDeviceAddRequest;
import com.xique.door.bean.request.AccessDevice.AccessDeviceEditRequest;
import com.xique.door.bean.request.AccessDevice.AccessDeviceRemoveRequest;
import com.xique.door.bean.search.UserDeviceSearch;
import com.xique.door.bean.transfer.AccessDeviceTransfer;
import com.xique.door.biz.service.IAccessDeviceBizService;
import com.xique.door.biz.service.IDeviceCommandNewService;
import com.xique.door.constant.AccessCommandConstant;
import com.xique.door.device.hk.bean.response.BasicResponse;
import com.xique.door.device.hk.service.HkCommandService;
import com.xique.door.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author shd
 * @create 2021/7/6 9:28
 */
@Service
@EnableAsync
@Slf4j
public class AccessDeviceBizServiceImpl implements IAccessDeviceBizService {

    @Autowired
    private IPermissionGroupUserService permissionGroupUserService;

    @Autowired
    private IAccessDeviceDomainService accessDeviceDomainService;

    @Autowired
    private IPermissionGroupDeviceService permissionGroupDeviceService;

    @Autowired
    private IUserDeviceService userDeviceService;

    @Autowired
    private IAccessDeviceService accessDeviceService;

    @Autowired
    private IDeviceCommandNewService deviceCommandNewService;

    @Autowired
    private HkCommandService hkCommandService;

    /**
     * 添加门禁设备
     * @author shd
     * @date 2021/7/6 9:29
     * @param request 入参
     * @return com.ruoyi.common.core.domain.AjaxResult
     * 1.添加设备信息到设备表 2.绑定设备到对应的权限组 3.绑定设备到对应用户 4.批量下发用户信息到设备
     */
    @Override
    public AjaxResult addDevice(AccessDeviceAddRequest request) {

        // 判断该设备是否已经被其他项目添加
        AccessDevice search = new AccessDevice();
        search.setDevSn(request.getDevSn());
//        List<AccessDevice> accessDeviceList = accessDeviceService.selectAccessDeviceList(search).stream().filter(item -> !request.getParkId().equals(item.getParkId())).collect(Collectors.toList());
//        if (!accessDeviceList.isEmpty()) {
//            return AjaxResult.error("该设备已被添加到其他项目");
//        }
        List<AccessDevice> accessDeviceList = accessDeviceService.selectAccessDeviceList(search);
        if (!accessDeviceList.isEmpty()){
            return AjaxResult.error("设备sn已存在！");
        }

        // 1.添加设备信息到设备表
        AccessDevice accessDevice = AccessDeviceTransfer.transferAccessDevice(request);

        // 2.绑定设备到对应的权限组
        List<Long> groupIds = Arrays.asList(Convert.toLongArray(request.getGroupIds()));
        List<PermissionGroupDevice> permissionGroupDevices = new ArrayList<>();
        groupIds.forEach(item -> {
            PermissionGroupDevice device = new PermissionGroupDevice();
            device.setGroupId(item);
            permissionGroupDevices.add(device);
        });

        // 3.绑定设备到对应用户
        List<UserDevice> userDevices = new ArrayList<>();
        List<PermissionGroupUser> permissionGroupUserList = permissionGroupUserService.selectPermissionGroupUserListByGroupIds(groupIds);
        permissionGroupUserList.forEach(item -> {
            UserDevice userDevice = new UserDevice();
            userDevice.setParkId(request.getParkId());
            userDevice.setGroupId(item.getGroupId());
            userDevice.setUserId(item.getUserId());
            userDevice.setDevSn(request.getDevSn());
            userDevices.add(userDevice);
        });

        boolean isSuccess = accessDeviceDomainService.addDevice(accessDevice, permissionGroupDevices, userDevices);
        if (!isSuccess) {
            return AjaxResult.error("添加失败");
        }

       //下发权限组用户至新设备
        AjaxResult result = deviceCommandNewService.addDeviceGroups(accessDevice, groupIds,true);

        return result;
    }

    /**
     * 编辑门禁设备
     * @author shd
     * @date 2021/7/6 13:37
     * @param request 入参
     * @return com.ruoyi.common.core.domain.AjaxResult
     * 1.修改设备表信息 2.修改绑定的权限组 3.修改绑定的用户 4.修改下发到设备的信息
     */
    @Override
    public AjaxResult editDevice(AccessDeviceEditRequest request) {

        //校验设备sn是否已存在
        AccessDevice deviceSearch = new AccessDevice();
        deviceSearch.setDevSn(request.getDevSn());
        List<AccessDevice> accessDeviceList = accessDeviceService.selectAccessDeviceList(deviceSearch).stream().filter(device -> !request.getId().equals(device.getId())).collect(Collectors.toList());
        if (!accessDeviceList.isEmpty()){
            return AjaxResult.error("设备sn已存在！");
        }

        // 1.修改设备信息到设备表
        AccessDevice accessDevice = AccessDeviceTransfer.transferAccessDevice(request);

//        List<String> devSns = Collections.singletonList(accessDevice.getDevSn());

        // 2.修改绑定的权限组
        List<Long> groupIds = Arrays.asList(Convert.toLongArray(request.getGroupIds()));
        List<PermissionGroupDevice> permissionGroupDevicesOld = permissionGroupDeviceService.selectPermissionGroupDeviceListByDeviceIds(Collections.singletonList(request.getId()));
        List<Long> groupIdsOld = permissionGroupDevicesOld.stream().map(PermissionGroupDevice::getGroupId).collect(Collectors.toList());
        List<Long> updateGroupIds = groupIds.stream().filter(g -> !groupIdsOld.contains(g)).collect(Collectors.toList());
        List<Long> deleteGroupIds = groupIdsOld.stream().filter(g -> !groupIds.contains(g)).collect(Collectors.toList());

        // 2.1.新增设备到权限组
        List<PermissionGroupDevice> updateGroupDevices = new ArrayList<>();
        updateGroupIds.forEach(item -> {
            PermissionGroupDevice device = new PermissionGroupDevice();
            device.setGroupId(item);
            device.setDeviceId(accessDevice.getId());
            updateGroupDevices.add(device);
        });

        // 2.2.删除权限组内的设备
        List<Long> deleteGroupDeviceIds = permissionGroupDevicesOld.stream().filter(item -> deleteGroupIds.contains(item.getGroupId())).map(PermissionGroupDevice::getId).collect(Collectors.toList());

        // 3.修改绑定的用户
        List<UserDevice> updateUserDevices = new ArrayList<>();
        // 3.1.新增绑定的用户
//        List<Long> updateUserIds = new ArrayList<>();
        if (updateGroupIds.size() > 0) {
            List<PermissionGroupUser> permissionGroupUserList = permissionGroupUserService.selectPermissionGroupUserListByGroupIds(updateGroupIds);
            permissionGroupUserList.forEach(item -> {
                UserDevice userDevice = new UserDevice();
                userDevice.setParkId(accessDevice.getParkId());
                userDevice.setGroupId(item.getGroupId());
                userDevice.setUserId(item.getUserId());
                userDevice.setDeviceId(accessDevice.getId());
                userDevice.setDevSn(accessDevice.getDevSn());
                updateUserDevices.add(userDevice);
            });
//            updateUserIds = permissionGroupUserList.stream().map(PermissionGroupUser::getUserId).collect(Collectors.toList());
        }

        // 3.2.删除解绑的用户
        List<Long> deleteUserDeviceIds = new ArrayList<>();
        List<Long> deleteUserIds = new ArrayList<>();
        if (deleteGroupIds.size() > 0) {
            UserDeviceSearch search = new UserDeviceSearch();
            search.setParkId(accessDevice.getParkId());
            search.setGroupIds(deleteGroupIds);
            search.setDeviceId(accessDevice.getId());
            List<UserDevice> userDeviceList = userDeviceService.selectUserDeviceListBySearch(search);
            deleteUserDeviceIds = userDeviceList.stream().map(UserDevice::getId).collect(Collectors.toList());
//            deleteUserIds = userDeviceList.stream().map(UserDevice::getUserId).distinct().collect(Collectors.toList());
        }

//        List<UserDevice> deleteUserDeviceList = userDeviceService.selectUserDeviceListByUserIdsAndDeviceIds(accessDevice.getParkId(), deleteUserIds, Collections.singletonList(accessDevice.getId()));


        try {
            //新增权限组:下发权限组用户至设备
            deviceCommandNewService.addDeviceGroups(accessDevice, updateGroupIds,false);
            //删除权限组:下发删除用户信息到设备
            deviceCommandNewService.delDeviceGroups(accessDevice,deleteGroupIds);
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("权限组变更下发失败，请联系管理员！");
        }

        boolean isSuccess = accessDeviceDomainService.editDevice(accessDevice, updateGroupDevices, deleteGroupDeviceIds, updateUserDevices, deleteUserDeviceIds);
        if (!isSuccess) {
            return AjaxResult.error("编辑失败");
        }

//        // 4.修改下发到设备的信息
//        // 4.1.新增下发用户到设备
//        List<User> updateUserList = userService.selectUserByIds(updateUserIds, UserConstant.Status.NORMAL);
//        applicationContext.publishEvent(new AddDeviceCommandEvent(accessDevice.getDevSn(), updateUserList));

//        // 4.2.删除用户信息到设备
//        List<Long> userIds = deleteUserDeviceList.stream().map(UserDevice::getUserId).distinct().collect(Collectors.toList());
//        List<Long> finalUpdateUserIds = updateUserIds;
//        userIds = userIds.stream().filter(item -> !finalUpdateUserIds.contains(item)).collect(Collectors.toList());
//        List<User> userList = userService.selectUserByIds(userIds, UserConstant.Status.NORMAL);
//        List<String> customIds = userList.stream().map(User::getCustomId).collect(Collectors.toList());
//        applicationContext.publishEvent(new DelDeviceCommandEvent(devSns, customIds));



        return AjaxResult.success("编辑完成");
    }

    /**
     * 删除门禁设备
     * @author shd
     * @date 2021/7/7 8:46
     * @param request 入参
     * @return com.ruoyi.common.core.domain.AjaxResult
     * 1.删除用户设备表 2.删除权限组设备 3.删除用户设备 4.下发删除用户信息到设备
     */
    @Override
    @Transactional
    public AjaxResult removeDevice(AccessDeviceRemoveRequest request) {

        Long parkId = request.getParkId();

        // 1.删除用户设备表
        List<Long> deviceIds = Arrays.asList(Convert.toLongArray(request.getIds()));

        // 2.删除权限组设备
        List<PermissionGroupDevice> permissionGroupDeviceList = permissionGroupDeviceService.selectPermissionGroupDeviceListByDeviceIds(deviceIds);
        List<Long> groupDeviceIds = permissionGroupDeviceList.stream().map(PermissionGroupDevice::getId).collect(Collectors.toList());

        // 3.删除用户设备
        UserDeviceSearch search = new UserDeviceSearch();
        search.setParkId(parkId);
        search.setDeviceIds(deviceIds);
        List<UserDevice> userDeviceList = userDeviceService.selectUserDeviceListBySearch(search);
        if (!userDeviceList.isEmpty() ||!permissionGroupDeviceList.isEmpty()){
          //  查询设备是否有和权限组绑定 || 设备和用户有绑定
            return AjaxResult.error("设备已经绑定了权限组或用户，请解除绑定后再删除设备!");
        }

        List<Long> userDeviceIds = userDeviceList.stream().map(UserDevice::getId).collect(Collectors.toList());

        AccessDevice accessDevice = accessDeviceService.selectAccessDeviceById(deviceIds.get(0));
        if (accessDevice.getModel().equals(AccessCommandConstant.DeviceType.HK) ) {
            BasicResponse basicResponse = hkCommandService.deleteDevice(accessDevice.getDevSn());
            log.info("delete hk device:" + basicResponse.toString());
        }

        boolean isSuccess = accessDeviceDomainService.removeDevice(deviceIds, groupDeviceIds, userDeviceIds);
        if (!isSuccess) {
            return AjaxResult.error("删除失败");
        }

        return AjaxResult.success();
    }
}
